/*
 * @Description:  VueRouter模拟实现练习
 * @version: 
 * @Author: hui.wang01
 * @Date: 2021-01-03 15:38:45
 * @LastEditors: hui.wang01
 */
let _Vue = null
export default class VueRouter {
  static install(Vue) {
    
    // 1.判断当前插件是否已经被安装
    if(VueRouter.install.installed){ //判断是否执行过install方法，执行过就直接返回，未执行过就继续
      return 
    } 
    VueRouter.install.installed = true
    // 2.把Vue构造函数记录到全局变量中,
    // 方便在将来在VUE实例方法中使用 vue构造函数，例如，在创建组件时需要调用Vue.component
    _Vue = Vue;

    // 3.将创建Vue实例时传入的router对象注入到所有Vue实例上   !!!!!!
    // this.$router就是此时挂载到vue实例上的，且所有组件都是Vue实例
    _Vue.minxin({
      beforeCreate() {
        if(this.options.router){  
          _Vue.prototype.$router = this.options.router
        }
        this.init(_Vue)
      }
    })
  }

  constructor(options) {
    this.options = options
    this.routeMap = []  //路由规则表，键值对形式
    this.data = _Vue.observable({  // 响应式数据 current
      current:''
    })
  }
  
  init(Vue) {
    this.createRouteMap()
    this.initComponents(Vue)
    this.initEvent()
  }
  createRouteMap () {
    // 遍历所有的路由规则，把路由规则解析成键值对的形式，存储到routeMap中
    this.options.routes.forEach(item => {
      this.routeMap[item.path] = item.component
    })
  }

  initComponents(Vue) {
    Vue.component('router-link',{
      props:{
        to: String
      },
      render (h) {
        return h('a',{          
          attrs: {
            href: this.to
          }
        },[this.$slots.default]) //这里是$slots,不是$slot!!!
        // $this.$slots.default获取默认插槽的内容；

      }
    })

    let self = this
    // 将当前的vueRouter实例保存到self变量中，因为组件router-view中的render函数中的this的指向不是当前vueRouter实例，

    Vue.component('router-view',{
      render (h){
        const component = self.routeMap[self.data.current]
        return h(component)
      }
    })
  }

  initEvent () {
    window.addEventListener('hashchange',() => {
      this.data.current = window.location.hash.substr(1)
    })
  }
}